<template>
  <div class="component-tab">
    <div class="search-box">
      <el-input v-model="searchValue" class="search-input" placeholder="搜索" size="mini" clearable />
    </div>
    <main v-loading="treeLoading" class="toolbox">
      <div class="tree-total-container">
        <div class="left-total">
          <span class="text">算子总数</span>
          <span class="tree-node-total">{{ operatorNum }}</span>
        </div>
        <div class="tree-button-group">
          <el-tooltip class="item" effect="dark" content="刷新算子列表 (Ctrl+Alt+R)" placement="top">
            <el-button class="tree-refresh" type="text" @click="getTreeData()">
              <svg-icon icon-class="shuaxin" />
            </el-button>
          </el-tooltip>

          <el-tooltip class="item" effect="dark" content="定位" placement="top">
            <el-button class="tree-refresh" type="text" @click="locationNode()">
              <svg-icon icon-class="dingwei" />
            </el-button>
          </el-tooltip>
          <el-tooltip class="item" effect="dark" :content="(treeExpanded === 'open' ? '折叠' : '展开') + ' (Ctrl+Alt+F)'"
            placement="top">
            <el-button class="tree-refresh" type="text" @click="updateTreeExpanded()">
              <svg-icon :icon-class="treeExpanded === 'open' ? 'a-zhedie1616' : 'expand'" />
            </el-button>
          </el-tooltip>
        </div>
      </div>
      <el-tree v-if="treeFilterData.length > 0" id="stencil-container" ref="tree" :data="treeFilterData" node-key="id"
        :default-expand-all="true" :expand-on-click-node="false" :props="{
          children: 'resources'
        }" @node-click="handleNodeClick">
        <template #default="{ node }">
          <el-popover placement="right-start" popper-class="module-card-info" width="264" trigger="hover" :offset="0"
            :close-delay="0" :disabled="node.data.nodeType !== 'algoNode'" :transition="''">
            <div v-if="node.data.nodeType === 'algoNode'" class="module-card-body">
              <div class="card-header">
                <h2 class="card-header-name">{{ node.label }}</h2>
                <div v-if="node.data" class="card-header-state" :class="{ 'private': node.data.is_enable }">
                  <!-- {{ node.data.is_enable ? '启用' : '禁用' }} -->
                  启用
                </div>
              </div>
              <algo-info :node-data="node.data" />
            </div>
            <template #reference>
              <span v-if="node.disabled" class="second-level-title toolbox-group-title">
                <svg-icon icon-class="jiedian" :style="{ fill: '#0000CC' }" />
                <span class="label">{{ node.label }}</span>
                <span v-if="!node.isLeaf" class="tree-node-total">{{ node.data.select_total || node.data.resources_total
                }}</span>
                <el-icon v-if="node.expanded">
                  <ArrowUp />
                </el-icon>
                <el-icon v-else>
                  <ArrowDown />
                </el-icon>
              </span>
              <span v-else class="toolbox-group-title" @mousedown="dragStencil($event, node)">
                <svg-icon-file :icon-class="node.data.icon || 'jiedianguanli'"
                  :style="{ fill: node.data.fill || '#0080ff' }" />
                <span class="label">{{ node.label }}</span>
                <span v-if="!node.isLeaf" class="tree-node-total">{{ node.data.select_total || node.data.resources_total
                }}</span>
                <el-icon v-if="node.expanded && !node.isLeaf">
                  <ArrowUp />
                </el-icon>
                <el-icon v-if="!node.expanded && !node.isLeaf">
                  <ArrowDown />
                </el-icon>
              </span>
            </template>
          </el-popover>
        </template>
      </el-tree>
    </main>
  </div>
</template>
<script setup lang="ts">
import { ports } from 'src/pages/designerTool/canvas/DagEdit/graph/methods.js'
import { ref, computed, shallowRef, onMounted, nextTick, watch } from "vue"
import { dataTree, operatorIconConfig } from 'src/utils/designerTool/componentData'
import { designerStore } from 'src/stores/designerTool/designerTool'
import Mousetrap from 'mousetrap'
import AlgoInfo from 'src/pages/designerTool/canvas/DagEdit/components/AlgoInfo/index.vue'
import { descriptionHandle } from 'src/utils/designerTool/toole'
import { debounce } from 'throttle-debounce'
import SvgIconFile from '../workflow/svgIconFile.vue'
import dagGraph from 'src/pages/designerTool/canvas/DagEdit/graph/index.js'
import { useRouter } from 'vue-router';
import { getCategories } from 'src/api/designerTool'
const projectId = useRouter().currentRoute.value.params.project_id
const searchValue = ref('')
const treeData = shallowRef(<any>[])
const treeFilterData = shallowRef(<any>[])
const categoriesParent = ref(<Record<string, any>>{})
const store = designerStore()
const operatorNum = ref(0)
const treeExpanded = ref('open')
const tree = ref()
const debounceFunc = () => {
  debounce(500, () => treeFilter())
}
const activeItem = ref(null)

const iconConfig = computed<Record<string, any>>(() => {
  return operatorIconConfig
})
const viewVersion = computed(() => {
  return !!store.versionId
})
const viewExperiment = computed(() => {
  return !!store.experimentId || !!store.flowReadonlyId
})
const readonly = computed(() => {
  return viewVersion.value || viewExperiment.value
})
const apiTreeData = shallowRef(<any>[])
watch(() => store.versionId, (newData, oldData) => {
  getTreeData()
})

getTreeData()
function getTreeData() {
  let dataReadIdList: any = []
  getCategories(store.project_id, { has_resource: true }).then((res: any) => {
    res.data.forEach((row: any) => {
      row['label'] = row.description
      row['icon'] = iconConfig.value[row.label] ? iconConfig.value[row.label].icon : ''
      row['fill'] = iconConfig.value[row.label] ? iconConfig.value[row.label].fill : ''
      categoriesParent.value[row.id] = {
        icon: row.icon,
        fill: row.fill
      }
      // 把数据读取的id存起来,导入的时候用
      if (row.name === 'datasource' && row.resources && Array.isArray(row.resources) && row.resources.length) {
        dataReadIdList = row.resources.filter((e:any) => e.id && e.operator && e.operator.id).map((e:any) => e.operator.id)
      }
    })
    apiTreeData.value = res.data
    store.SET_DATA_READ_ID_LIST(dataReadIdList)
    treeDataHandle(apiTreeData.value, store.categoriesParent, store.categoriesSubset, store.operatorConfig)
    operatorNum.value = Object.keys(store.categoriesSubset).length
    store.SET_CATEGORIES_PARENT(categoriesParent.value)
    store.SET_CATEGORIES_SUBSET(store.categoriesSubset)
    store.SET_OPERATOR_CONFIG(store.operatorConfig)
    treeData.value = apiTreeData.value
    treeFilterData.value = apiTreeData.value
    nextTick(() => {
      if (searchValue.value) {
        debounceFunc()
      }
    })
    store.SET_PUBLISH_EVENT({
      key: 'loadWorkflowInfo',
      data: 'init'
    })

  })
}
function handleNodeClick(node:any) {
  if (!node.isLeaf) {
    if (node.expanded) {
      node.collapse()
    } else {
      node.expand()
    }
  }
}
// onMounted(() => {
//   nextTick(() => {
//     initEvent()
//   })
// })
watch(() => store.events.initEvent.index, (newData, oldData) => {
  initEvent()
})
function initEvent() {
  if (!readonly.value) {
    dagGraph.initStencilTree('stencil-container')
    Mousetrap.bind('ctrl+alt+f', () => {
      updateTreeExpanded()
      return false
    })
    Mousetrap.bind('ctrl+alt+r', () => {
      if (!store.leftPanel) {
        store.SET_LEFT_PANEL(true)
        store.SET_PUBLISH_EVENT({
          key: 'viewResize',
          data: 'init'
        })
      }
      getTreeData()
      return false
    })
  }
}
// function getWorkflowInfoError(res) {
//   this.$confirm(res ? res.result : '请求错误', '获取基础数据错误', {
//     confirmButtonText: '重新获取',
//     showClose: false,
//     showCancelButton: false,
//     closeOnClickModal: false,
//     closeOnPressEscape: false,
//     dangerouslyUseHTMLString: true,
//     type: 'error'
//   }).then(() => {
//     this.getTreeData()
//   }).catch(error => {
//     console.log(error)
//   })
// }
function treeDataHandle(data: Array<any>, categoriesParent: any, categoriesSubset: any, operatorConfig: any) {
  data.forEach(row => {
    row['select_total'] = 0
    if (row.resources && Array.isArray(row.resources)) {
      for (let i = 0; i < row.resources.length; i++) {
        row.resources[i] = row.resources[i].operator
        row.resources[i]['description'] = descriptionHandle(row.resources[i].description)
        row.resources[i]['nodeType'] = 'algoNode'
        row.resources[i]['parentId'] = row.parentId || row.id
        row.resources[i]['icon'] = ''
        store.categoriesSubset[row.resources[i].id] = row.resources[i]
        // operatorConfigHandle(row.resources[i], operatorConfig)
      }
    }
    if (row.nodes && row.nodes.length) {
      row.nodes.forEach((node:any) => {
        node['label'] = node.description
        node['disabled'] = true
        node['parentId'] = row.id
        store.categoriesParent[node.id] = categoriesParent[row.id]
      })
      treeDataHandle(row.nodes, store.categoriesParent, store.categoriesSubset, store.operatorConfig)
      row.resources = row.resources.concat(row.nodes)
    }
    delete row.nodes
  })
}
// 拖拽事件
function dragStencil(event:any, row:any) {
  store.SET_OPERATOR_DATA(row)
  if (!row.isLeaf || row.level === 1) return
  const items = <any>[]
  if (row.data) {
    row.data.configs.forEach((ele: any, index: string) => {
      if (ele.param_type == 'input') {
        items.push(
          {
            id: ele.id,
            group: 'inputs',
          })
      }
      if (ele.param_type == 'output') {
        items.push({
          id: ele.id,
          group: 'outputs'
        })
      }
    })
  }
  interface objectType {
    [key: string]: string | number | undefined | null | void | object
  }
  const configs = <objectType>{
    id: row.id,
    name: row.name,
    value: row.default_value
  }
  // if (row?.data?.configs) {
  //   for (const key in row.data.configs) {
  //     console.log(key)
  //     const rowNode = row.data.configs[key]
  //     configs[key] = []
  //     rowNode.results.forEach((sectionRow: any) => {
  //       sectionRow.results.forEach(row => {
  //         configs[key].push({
  //           id: row.id,
  //           name: row.name,
  //           value: row.default_value
  //         })
  //       })
  //     })
  //   }
  // }
  // console.log(row)
  // console.log(configs)
  // console.log(items)

  const node = dagGraph.graph?.createNode({
    size: {
      width: 220,
      height: 38
    },
    shape: 'vue-shape',
    ports: {
      groups: ports.groups,
      items: items
    },
    component: 'algo-node',
    data: {
      id: row.data.id,
      status: 'Scheduled',
      desc: '',
      configs: configs
    }
  })
  dagGraph.dnd.start(node, event)
}
function updateTreeExpanded() {
  treeExpanded.value = treeExpanded.value === 'open' ? 'fold' : 'open'
  if (treeExpanded.value) {
    const nodes = tree.value.store.root.childNodes
    for (let i = 0; i < nodes.length; i++) {
      const row = nodes[i]
      if (!row.isLeaf) {
        row.expanded = treeExpanded.value === 'open'
      }
      if (row.childNodes) {
        for (let j = 0; j < row.childNodes.length; j++) {
          if (!row.childNodes[j].isLeaf) {
            row.childNodes[j].expanded = treeExpanded.value === 'open'
          }
        }
      }
    }
  }
}
function locationNode() {
  if (store.selectedId) {
    const node = dagGraph.graph?.getCellById(store.selectedId)
    if (node) {
      const nodeData = node.getData()
      const { parentId, category_id } = store.categoriesSubset[nodeData.id]
      const parentNode = tree.value.getNode(parentId)
      if (!parentNode.expanded) {
        parentNode.expanded = true
      }
      if (parentId !== category_id) {
        const categoryNode = tree.value.getNode(category_id)
        if (!categoryNode.expanded) {
          categoryNode.expanded = true
        }
      }
      const label = store.categoriesSubset[nodeData.id].label
      if (label) {
        setTimeout(() => {
          locationItem(label)
        }, 200)
      }
    } l
  }
}
function locationItem(label:any) {
  let itemIndex = -1
  for (let i = 0; i < tree.value.treeItems.length; i++) {
    const item = tree.value.treeItems[i]
    if (item.innerText === label) {
      itemIndex = i
    }
  }
  if (activeItem.value) {
    activeItem.value.className = 'el-tree-node__content'
  }
  if (itemIndex !== -1) {
    const item = tree.value.treeItems[itemIndex]
    activeItem.value = item.childNodes[0]
    item.childNodes[0].className += ' active'
    tree.value.$el.scrollTo(0, item.offsetTop)
  }
}
function treeFilter() {
  operatorNum.value = 0
  treeFilterData.value = traverse(JSON.parse(JSON.stringify(treeData.value)))
  treeExpanded.value = 'open'
}
function traverse(data:any) {
  return data.filter((item:any) => {
    if (item.resources) {
      item.resources = traverse(item.resources)
      item.select_total = 0
      item.resources.forEach((row:any) => {
        if (row.select_total) {
          item.select_total += row.select_total
        } else {
          item.select_total++
          operatorNum.value++
        }
      })
    }
    return item.label.indexOf(searchValue.value) !== -1 || !!item.select_total
  })
}

</script>
<style lang="scss" scoped>
@import "src/css/designerStyles/index.scss";

.component-tab {
  width: 100%;
  height: 100%;

  .search-box {
    padding: 2px 10px;
    border-bottom: 1px solid #dcdee2;
    display: flex;
    align-items: center;
    position: relative;
    height: 36px;

    .el-dropdown {
      margin-left: 6px;

      .search-setting-button {
        color: #606266;
        font-size: 17px;
        padding: 0;
      }
    }

    &::v-deep .search-input {
      .el-input__inner {
        border: 0;
        padding-left: 0;
      }

      .el-input__suffix {
        right: 0;
      }
    }
  }

  .toolbox {
    flex: 1;
    height: calc(100vh - 72px);

    .tree-total-container {
      height: 33px;
      display: flex;
      align-items: center;
      padding: 0 10px;
      justify-content: space-between;
      border-bottom: 1px solid #dcdee2;

      .left-total {
        .text {
          color: #606266;
        }

        .tree-node-total {
          margin-left: 6px;
        }
      }

      .tree-refresh {
        color: #606266;
        font-size: 17px;
        padding: 0;
      }
    }

    .el-tree {
      overflow-y: auto;
      height: calc(100% - 33px);
    }

    &::v-deep .el-tree-node {
      line-height: 34px;

      .el-tree-node__expand-icon {
        display: none;
      }

      .el-tree-node__content {
        cursor: pointer;
        background: #fff;
        border-bottom: 1px solid #dcdee2;
        height: 34px;
        padding-left: 12px !important;
        padding-right: 12px !important;

        &>span:last-child {
          flex: 1;
          width: 100%;

          .el-popover__reference-wrapper {
            display: flex;
            width: 100%;
          }
        }

        .icon {
          margin-right: 8px;
          color: #99CCFF;
        }

        .toolbox-group-title {
          flex: 1;
          display: flex;
          align-items: center;
          width: 100%;

          .svg-icon {
            margin-right: 6px;
          }

          .label {
            flex: 1;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            -webkit-user-select: none;
          }

          .tree-node-total {
            margin-right: 6px;
          }
        }
      }

      .second-level-title {
        background: white;
      }

      .el-tree-node__children {
        .is-leaf {
          display: none;
        }

        .el-tree-node__content {
          background: #F8FAFB;
          padding: 0 !important;

          &:hover {
            background-color: #f0f1f3;
          }

          .toolbox-group-title {
            height: 100%;
            width: 100%;
            padding-left: 24px;
            padding-right: 12px;
          }

          .second-level-title {
            background: white;
          }

          &.active {
            background: #ecf5ff;
          }
        }
      }
    }
  }

  .tree-node-total {
    background: #E9E9EB;
    color: #4F4F4F;
    font-size: 12px;
    border-radius: 50%;
    min-width: 20px;
    height: 20px;
    text-align: center;
    line-height: 20px;
    padding-right: 1px;
    display: inline-block;
  }
}
</style>
<style lang="scss">
.module-card-info {
  .module-card-body {
    p {
      margin: 0;
    }

    .template-entry {
      user-select: auto;
      cursor: pointer;
      color: #1b5bd8;
      line-height: 22px;
      padding: 4px 0 6px;
    }

    .card-header {
      display: flex;
      line-height: 1.6em;
      padding-bottom: 6px;
      align-items: flex-start;

      .card-header-name {
        margin: 0 auto 0 0;
        color: #333;
        font-size: inherit;
        padding-right: 10px;
        flex: 1;
      }

      .card-header-state {
        background-color: #e5f2ff;
        border-radius: 2px;
        color: #1b5bd8;
        border: 1px solid #e5f2ff;
        padding: 0 6px;

        &.private {
          border-color: #fdf7e5;
          background-color: #fdf7e5;
          color: #9b7b0d;
        }
      }
    }

    .card-desc-content {
      text-align: justify;
      color: #333;
      line-height: 1.5em;
      padding-bottom: 3px;
    }

    .card-footer-column {
      line-height: 1.5em;
      padding: 3px 0;

      .caption {
        color: #808695;
      }

      .content {
        word-break: break-all;
        color: #333;
      }
    }
  }
}
</style>
